JavaScript的闭包与函数重载
闭包的概念
什么是闭包
说到JavaScript的闭包,需要先说一说JavaScript的作用域。
JavaScript在ECMA6之前,作用域是只有全局作用域跟函数作用域的。(这里先不涉及let和const)
函数内部可以读取器外部作用域定义的变量,而外部作用域不能直接读取到函数中定义的变量。
eg:
var n = 0; |
上述例子中,函数f1在运行时可以访问到全局作用域定义的变量n。而全局作用域中无法访问到函数f2中定义的变量a。
那么还有一个例子:
var n = 0; |
上述例子中的,函数f1中定义了函数f2,f2能够访问到f1中定义的变量a以及全局作用域中定义的变量n。那么,这可以说明,更里层的函数能够访问到更外层的作用域中定义的变量。而更外层的代码,无法访问到更里层的函数作用域定义的变量。这是JavaScript链式作用域的作用。
那么,如果我们有需要在全局作用域中访问到函数作用域中定义的变量,那应该怎么做呢?
我们发现函数f2是能够访问到f1中定义的变量的。那么将他返回到全局作用域:
function f1() { |
那么,上述的函数f2,就是一个闭包。
闭包是用于读取其他函数内部变量的函数(取自@阮一峰老师的博客)
闭包的特性
1.闭包可以读取其他函数内部变量。
这个特性这里不再赘述
2.闭包会将函数内部的局部变量存储在内存中
如上一节最后一个例子,函数f2将变量a保存在内存中,然后在被调用时,就能够访问到了。
那么,利用这个特性,我们可以做一个类似于计数器的东西:
eg:
function counter() { |
这个特性也会导致一个问题,就是如果滥用闭包的话,内存消耗会比较多。
利用闭包来定义私有变量
利用闭包的特性,我们可以利用闭包做私有变量:
var ClassA = function () { |
这里的a变量只能被ClassA以及getA和setA访问到。
利用闭包做函数重载
最近学习到了一个在JavaScript中实现函数重载的方法,感觉比较有趣。
众所周知JavaScript的函数的参数是不固定的,所以没办法做函数重载。如果要实现类似于函数重载的方法,比较平常的做法是使用if-else
或switch
来判断参数,然后根据传入的参数不同,输出不同的结果。
而最近学习了一个,利用闭包处理的比较干净一些的做法。
1.准备阶段先撸一下需要存放重载函数的类/对象
var object = {}; |
2.定义需要重载的函数。
function sum0(val0) { |
3.然后定义装载重载函数的函数(核心):
function addMethod(object, name, f) { |
4.装载函数:
addMethod(people, "add", add0); |
上述代码使用old存储上一次调用addMethod方法加入的函数。然后通过闭包存储在内存中。使得每次调用add函数时,出现参数不等的情况时能够调用到old,以查找到上一个add进来的函数。最终达到函数重载的目的。